﻿
using CSharpLibs.Annotations;

namespace System.Collections.Generic
{
	/*
	[Builtin]
	public sealed class HashSet<T0> : Object, ISet<T0>, ICollection<T0>, IEnumerable<T0>, IEnumerable
	{
		// Fields
		private Entry[] m_values;
		private int m_card;

		public HashSet()
		{
			this.m_values = new Entry[4];
			for(int i = 0; i < 4; ++i)
				this.m_values[i] = new Entry(-1);

			this.m_card = 0;
		}

		public HashSet(IEnumerable<T0> collection)
			: this()
		{
			foreach(T0 val in collection)
				this.Add(val);
		}

		public bool Add(T0 value)
		{
			if(this.Contains(value))
				return false;

			int hc = InternalGetHashCode(value);
			return this.Add_NoContains(value, hc);
		}

		public bool Add_NoContains(T0 value, int hcinternal)
		{
			if(1.5 * (this.m_card + 1) >= this.m_values.Length)
				this.IncreaseCapacity();

			int inspos = this.InternalGetTableIndexFromHash(hcinternal);

			if(this.m_values[inspos].hash == -1)
				this.m_values[inspos] = new Entry(hcinternal, value, -1);
			else
			{
				int epos = inspos;
				while(this.m_values[epos].link != -1)
					epos = this.m_values[epos].link;

				int fpos = this.NextOpenIndexFromPos(epos);
				this.m_values[fpos] = new Entry(hcinternal, value, -1);
				this.m_values[epos].link = fpos;
			}

			return true;
		}

		public void Clear()
		{
			for(int i = 0; i < this.m_values.Length; ++i)
				this.m_values[i] = new Entry(-1);

			this.m_card = 0;
		}

		public bool Contains(T0 item)
		{
			int hc = InternalGetHashCode(item);
			int pos = this.InternalGetTableIndexFromHash(hc);

			Entry e = this.m_values[pos];
			while(e.hash != -1)
			{
				if(EqualityComparer<T0>.DefaultEquals(e.value, item))
					return true;

				e = (e.link != -1) ? this.m_values[e.link] : new Entry(-1);
			}

			return false;
		}

		private bool ContainsAllElements(IEnumerable<T0> other)
		{
			foreach(T0 local in other)
			{
				if(!this.Contains(local))
					return false;
			}
			return true;
		}

		public void CopyTo(T0[] array)
		{ this.CopyTo(array, 0, this.m_card); }

		public void CopyTo(T0[] array, int arrayIndex)
		{ this.CopyTo(array, arrayIndex, this.m_card); }

		public void CopyTo(T0[] array, int arrayIndex, int count)
		{
			int num = 0;
			for(int i = 0; (i < this.m_values.Length) && (num < count); i++)
			{
				if(this.m_values[i].hash != -1)
				{
					array[arrayIndex + num] = this.m_values[i].value;
					num++;
				}
			}
		}

		public void ExceptWith(IEnumerable<T0> other)
		{
			if(other == this)
				this.Clear();
			else
			{
				foreach(T0 local in other)
					this.Remove(local);
			}
		}

		public Enumerator GetEnumerator()
		{ return new Enumerator((HashSet<T0>)this); }

		private void IncreaseCapacity()
		{
			int newcap = this.m_values.Length * 2 + 4;
			Entry[] vals = new Entry[this.m_card];

			int num = 0;
			for(int i = 0; i < this.m_values.Length; i++)
			{
				if(this.m_values[i].hash != -1)
				{
					vals[num] = this.m_values[i];
					num++;
				}
			}

			Array.Resize(ref this.m_values, newcap);
			for(int i = 0; i < this.m_values.Length; ++i)
				this.m_values[i] = new Entry(-1);

			for(int i = 0; i < vals.Length; ++i)
				this.Add_NoContains(vals[i].value, vals[i].hash); 
		}

		private static int InternalGetHashCode(T0 item)
		{
			if(item == null)
				return 0;

			return (EqualityComparer<T0>.DefaultGetHashCode(item) & 0x7fffffff);
		}

		private int InternalGetTableIndexFromHash(int hc)
		{ return hc % this.m_values.Length; }

		private int NextOpenIndexFromPos(int pos)
		{
			for(int i = pos; i < this.m_values.Length; ++i)
			{
				if(this.m_values[i].hash == -1)
					return i;
			}

			for(int j = 0; j < pos; ++j)
			{
				if(this.m_values[j].hash == -1)
					return j;
			}

			throw new ArgumentException("Check capacity first!!");
		}

		public void IntersectWith(IEnumerable<T0> other)
		{
			HashSet<T0> ohs;
			if(other is HashSet<T0>)
				ohs = (HashSet<T0>)other;
			else
				ohs = new HashSet<T0>(other);

			List<T0> imissing = new List<T0>();

			IEnumerator<T0> he = this.GetEnumerator();
			while(he.MoveNext())
			{
				if(!ohs.Contains(he.Current))
					imissing.Add(he.Current);
			}

			for(int i = 0; i < imissing.Count; ++i)
				this.Remove(imissing[i]);
		}

		public bool IsSubsetOf(IEnumerable<T0> other)
		{
			HashSet<T0> ohs;
			if(other is HashSet<T0>)
				ohs = (HashSet<T0>)other;
			else
				ohs = new HashSet<T0>(other);

			Enumerator he = this.GetEnumerator();
			while(he.MoveNext())
			{
				if(!ohs.Contains(he.Current))
					return false;
			}

			return true;
		}

		public bool IsSupersetOf(IEnumerable<T0> other)
		{
			IEnumerator<T0> he = other.GetEnumerator();
			while(he.MoveNext())
			{
				if(!this.Contains(he.Current))
					return false;
			}

			return true;
		}

		public bool Overlaps(IEnumerable<T0> other)
		{
			IEnumerator<T0> he = other.GetEnumerator();
			while(he.MoveNext())
			{
				if(this.Contains(he.Current))
					return true;
			}

			return false;
		}

		public bool Remove(T0 item)
		{
			if(this.m_card != 0)
			{
				if(!this.Contains(item))
					return false;

				int hc = InternalGetHashCode(item);
				int rempos = this.InternalGetTableIndexFromHash(hc);

				if(EqualityComparer<T0>.DefaultEquals(this.m_values[rempos].value, item))
				{
					if(this.m_values[rempos].link == -1)
						this.m_values[rempos] = new Entry(-1);
					else
					{
						int lpos = this.m_values[rempos].link;
						this.m_values[rempos] = this.m_values[lpos];
						this.m_values[lpos] = new Entry(-1);
					}
				}
				else
				{
					int prevpos = rempos;
					int nextpos = this.m_values[prevpos].link;
					while(!EqualityComparer<T0>.DefaultEquals(this.m_values[nextpos].value, item))
					{
						prevpos = nextpos;
						nextpos = this.m_values[prevpos].link;
					}

					this.m_values[prevpos].link = this.m_values[nextpos].link;
					this.m_values[nextpos] = new Entry(-1);
				}

				return true;
			}

			return false;
		}

		public int RemoveWhere(Predicate<T0> match)
		{
			int num = 0;

			T0[] contents = new T0[this.m_card];
			this.CopyTo(contents);

			for(int i = 0; i < contents.Length; ++i)
			{
				if(match(contents[i]))
				{
					this.Remove(contents[i]);
					num++;
				}
			}

			return num;
		}

		public bool SetEquals(IEnumerable<T0> other)
		{
			HashSet<T0> ohs;
			if(other is HashSet<T0>)
				ohs = (HashSet<T0>)other;
			else
				ohs = new HashSet<T0>(other);

			if(this.m_card != ohs.m_card)
				return false;

			Enumerator he = this.GetEnumerator();
			while(he.MoveNext())
			{
				if(!ohs.Contains(he.Current))
					return false;
			}

			return true;
		}

		void ICollection<T0>.Add(T0 item)
		{ this.Add(item); }

		IEnumerator<T0> IEnumerable<T0>.GetEnumerator()
		{ return new Enumerator((HashSet<T0>)this); }

		IEnumerator IEnumerable.GetEnumerator()
		{ return new Enumerator((HashSet<T0>)this); }

		internal T0[] ToArray()
		{
			T0[] array = new T0[this.Count];
			this.CopyTo(array);
			return array;
		}

		public void UnionWith(IEnumerable<T0> other)
		{
			IEnumerator<T0> he = other.GetEnumerator();
			while(he.MoveNext())
				this.Add(he.Current);
		}

		public int Count
		{ get { return this.m_card; } }

		[Builtin]
		public struct Enumerator : IEnumerator<T0>, IDisposable, IEnumerator
		{
			private HashSet<T0> set;
			private int index;

			internal Enumerator(HashSet<T0> set)
			{
				this.set = set;
				this.index = -1;
			}

			public void Dispose()
			{ ;}

			public bool MoveNext()
			{
				this.index++;

				while(this.index < this.set.m_values.Length)
				{
					if(this.set.m_values[this.index].hash >= 0)
						return true;

					this.index++;
				}

				return false;
			}

			public T0 Current
			{ get { return this.set.m_values[this.index].value; } }

			object IEnumerator.Current
			{ get { return this.Current; } }

			void IEnumerator.Reset()
			{ this.index = -1; }
		}

		[Builtin]
		public struct Entry
		{
			public readonly int hash;
			public readonly T0 value;
			public int link;

			public Entry(int h, T0 val, int nlink)
			{
				this.hash = h;
				this.value = val;
				this.link = nlink;
			}

			public Entry(int h)
			{
				this.hash = h;
				this.value = default(T0);
				this.link = -1;
			}
		}
	}
	*/
}
